package org.slusk.thynwor.neat;

import java.io.IOException;

import org.jgap.Chromosome;
import org.jgap.Configuration;
import org.slusk.thynwor.util.Util;

import com.anji.hyperneat.modular.ModularHyperNeatTranscriberFactory;
import com.anji.hyperneat.nd.ActivatorND;
import com.anji.hyperneat.nd.HyperNeatTranscriberND;
import com.anji.hyperneat.nd.NDActivatorArray;
import com.anji.hyperneat.onlinereinforcement.OnlineLearningNetType;
import com.anji.integration.ActivatorTranscriber;
import com.anji.integration.Transcriber;
import com.anji.integration.TranscriberException;
import com.anji.persistence.FilePersistence;
import com.anji.persistence.Persistence;
import com.anji.util.DummyConfiguration;
import com.anji.util.Properties;


public class ActivatableNetFactory {

	private static String baseConfigDirectory = "configs/";

	public static ActivatableNet createNet(String netType, String chromId) {
		ActivatableNet net = null;
		Properties props = null;
		
		try {
			props = new Properties("configs/"+netType+".properties");
			Persistence db = (Persistence) props.newObjectProperty( Persistence.PERSISTENCE_CLASS_KEY );
			Configuration config = new DummyConfiguration();
			Chromosome chrom = db.loadChromosome(chromId, config);
			ActivatorTranscriber at = new ActivatorTranscriber();
			at.init(props);
			net = new AnjiNetWrapper(at.newActivator(chrom));
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (TranscriberException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}


		return net;
	}
	
	public static String getBaseConfigDirectory() {return baseConfigDirectory;}
	public static void setBaseConfigDirectory(String baseConfigDirectory) {ActivatableNetFactory.baseConfigDirectory = baseConfigDirectory;}

	public static ActivatorND createGridNetND(String netType, String chromId) {
		ActivatorND net = null;
		Properties props = null;
		try {
			props = new Properties("configs/"+netType+".properties");
		} catch (IOException e) {
			System.out.println("ActivatableNetFactory.createGridNetND("+netType+", "+chromId+"): Couldn't load properties; can't continue.");
			return null;
		} catch (Exception e) {
			System.out.println("ActivatableNetFactory.createGridNetND("+netType+", "+chromId+"): Couldn't load properties; can't continue.");
			return null;
		}
		
		Persistence db = (Persistence) props.newObjectProperty( Persistence.PERSISTENCE_CLASS_KEY );
		Configuration config = new DummyConfiguration();
		Chromosome chrom = db.loadChromosome(chromId, config);
		HyperNeatTranscriberND transcriber = new HyperNeatTranscriberND(props);
		
		try {
			net = transcriber.newGridNetND(chrom, null);
		} catch (TranscriberException e) {
			System.out.println("ActivatableNetFactory.createGridNetND("+netType+", "+chromId+"): Failed to transcribe gridnet.");
		} catch (Exception e) {
			System.out.println("ActivatableNetFactory.createGridNetND("+netType+", "+chromId+"): Failed to transcribe gridnet.");
			return null;
		}
		
		return net;
	}
	
	public static NDActivatorArray createGridNets(String netType, String chromId) {
		// HACK
		NDActivatorArray nets = null; //new NDActivatorArray(new int[]{2});
		Properties props = null;
		try {
			props = new Properties("configs/"+netType+".properties");
		} catch (IOException e) {
			System.out.println("ActivatableNetFactory.createGridNetND("+netType+", "+chromId+"): Couldn't load properties; can't continue.");
			return null;
		} catch (Exception e) {
			System.out.println("ActivatableNetFactory.createGridNetND("+netType+", "+chromId+"): Couldn't load properties; can't continue.");
			return null;
		}
		
		OnlineLearningNetType learningType = OnlineLearningNetType.valueOf(props.getProperty("ann.hyperneat.online.learning.type"));
		
		Persistence db = (Persistence) props.newObjectProperty( Persistence.PERSISTENCE_CLASS_KEY );
		Configuration config = new DummyConfiguration();
		Chromosome chrom = db.loadChromosome(chromId, config);
//		com.anji.hyperneat.modular.ModularHyperNeatMultiNetTranscriber transcriber = new com.anji.hyperneat.modular.ModularHyperNeatMultiNetTranscriber(props);
		Transcriber<NDActivatorArray> transcriber = ModularHyperNeatTranscriberFactory.getMultinetTranscriber(props);
		
		try {
//			for (ActivatorArrayIterator net = nets.iterator(); net.hasNext(); net.next())
			nets = transcriber.transcribe(chrom, nets);
		} catch (TranscriberException e) {
			System.out.println("ActivatableNetFactory.createGridNetND("+netType+", "+chromId+"): Failed to transcribe gridnet.");
		} catch (Exception e) {
			System.out.println("ActivatableNetFactory.createGridNetND("+netType+", "+chromId+"): Failed to transcribe gridnet.");
			return null;
		}
		
		nets = learningType == OnlineLearningNetType.NONE ? nets : Util.buildLearningNets(nets, learningType);
		
		return nets;
	}
	
	public static NDActivatorArray createGridNets(Properties props) {
		NDActivatorArray nets = null; 
		OnlineLearningNetType learningType = OnlineLearningNetType.valueOf(props.getProperty("ann.hyperneat.online.learning.type"));
		
		FilePersistence db = new FilePersistence();
		Configuration config = new DummyConfiguration();
		String path = props.getProperty("LoadChromosomePath");
		Chromosome chrom = db.loadChromosomeByPath(path, config);
		Transcriber<NDActivatorArray> transcriber = ModularHyperNeatTranscriberFactory.getMultinetTranscriber(props);
		
		try {
			nets = transcriber.transcribe(chrom, nets);
		} catch (TranscriberException e) {
			System.out.println("ActivatableNetFactory.createGridNets(): Failed to transcribe gridnet for chromosome: " + path);
		} catch (Exception e) {
			System.out.println("ActivatableNetFactory.createGridNets(): Failed to transcribe gridnet for chromosome: " + path);
			return null;
		}
		
		nets = learningType == OnlineLearningNetType.NONE ? nets : Util.buildLearningNets(nets, learningType);
		
		return nets;
	}
	
	public static NDActivatorArray createGridNets(Properties props, String chromPath) {
		NDActivatorArray nets = null; 
		OnlineLearningNetType learningType = OnlineLearningNetType.valueOf(props.getProperty("ann.hyperneat.online.learning.type"));
		
		FilePersistence db = new FilePersistence();
		Configuration config = new DummyConfiguration();
		Chromosome chrom = db.loadChromosomeByPath(chromPath, config);
		Transcriber<NDActivatorArray> transcriber = ModularHyperNeatTranscriberFactory.getMultinetTranscriber(props);
		
		try {
			nets = transcriber.transcribe(chrom, nets);
		} catch (TranscriberException e) {
			System.out.println("ActivatableNetFactory.createGridNets(): Failed to transcribe gridnet for chromosome: " + chromPath);
		} catch (Exception e) {
			System.out.println("ActivatableNetFactory.createGridNets(): Failed to transcribe gridnet for chromosome: " + chromPath);
			return null;
		}
		
		nets = learningType == OnlineLearningNetType.NONE ? nets : Util.buildLearningNets(nets, learningType);
		
		return nets;
	}
}

